package com.xindacloud.sms.adapter.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xindacloud.sms.adapter.bo.SmsReportBO;
import com.xindacloud.sms.adapter.dao.SmsDeliveryReceiptMapper;
import com.xindacloud.sms.adapter.dto.SmsReportDTO;
import com.xindacloud.sms.adapter.entity.SmsDeliveryReceipt;
import com.xindacloud.sms.adapter.entity.SmsPricing;
import com.xindacloud.sms.adapter.entity.SmsUser;
import com.xindacloud.sms.adapter.service.CommonServiceImpl;
import com.xindacloud.sms.adapter.service.business.ISmsDeliveryReceiptService;
import com.xindacloud.sms.adapter.service.business.ISmsPricingService;
import com.xindacloud.sms.adapter.service.business.ISmsUserService;
import com.xindacloud.sms.adapter.vo.SmsReportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


@Slf4j
@Service
public class SmsDeliveryReceiptServiceImpl extends ServiceImpl<SmsDeliveryReceiptMapper, SmsDeliveryReceipt> implements ISmsDeliveryReceiptService {


    final SmsDeliveryReceiptMapper deliveryReceiptMapper;

    final ISmsPricingService pricingService;

    final ISmsUserService smsUserService;

    @Autowired
    CommonServiceImpl commonService;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    public SmsDeliveryReceiptServiceImpl(SmsDeliveryReceiptMapper deliveryReceiptMapper, ISmsPricingService pricingService,
                                         ISmsUserService smsUserService) {
        this.deliveryReceiptMapper = deliveryReceiptMapper;
        this.pricingService = pricingService;
        this.smsUserService = smsUserService;
    }

    @Override
    public boolean saveDeliveryReceipt(SmsDeliveryReceipt smsDeliveryReceipt) {

        QueryWrapper<SmsDeliveryReceipt> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("message_id", smsDeliveryReceipt.getMessageId());
        queryWrapper.eq("sent_to", smsDeliveryReceipt.getSentTo());

        final SmsDeliveryReceipt one = getOne(queryWrapper, true);

        if (Objects.isNull(one)) {
            return save(smsDeliveryReceipt);
        } else {
            return lambdaUpdate()
                    .set(SmsDeliveryReceipt::getStatus, smsDeliveryReceipt.getStatus())
                    .set(StringUtils.isNotEmpty(smsDeliveryReceipt.getErrorCode()),SmsDeliveryReceipt::getErrorCode,smsDeliveryReceipt.getErrorCode())
                    .set(StringUtils.isNotEmpty(smsDeliveryReceipt.getReason()),SmsDeliveryReceipt::getReason,smsDeliveryReceipt.getReason())
                    .set(StringUtils.isNotEmpty(smsDeliveryReceipt.getScts()), SmsDeliveryReceipt::getScts, smsDeliveryReceipt.getScts())
                    .set(Objects.nonNull(smsDeliveryReceipt.getMessageTimestamp()), SmsDeliveryReceipt::getMessageTimestamp, smsDeliveryReceipt.getMessageTimestamp())
                    .set(SmsDeliveryReceipt::getLastUpdateTime, LocalDateTime.now())
                    .eq(SmsDeliveryReceipt::getMessageId, smsDeliveryReceipt.getMessageId())
                    .eq(SmsDeliveryReceipt::getSentTo, smsDeliveryReceipt.getSentTo())
                    .update();
        }
    }


    @Override
    public List<SmsReportVO> querySmsReportFor(SmsReportDTO smsReportDTO, String username, String password) {


        SmsReportBO smsReportBO = new SmsReportBO();
        BeanUtils.copyProperties(smsReportDTO, smsReportBO);
        final SmsUser smsUser = commonService.getSmsUser(username, password);
        if (Objects.isNull(smsUser)) {
            return Collections.emptyList();
        }
        List<Integer> finalUserIdList = commonService.queryUserIdsFor(smsUser.getUserId());
        smsReportBO.setUserIds(finalUserIdList);
        final List<SmsReportVO> reportVOList = deliveryReceiptMapper.querySmsReportFor(smsReportBO).stream()
                .peek(rs -> {

                    rs.setCountryName(getSmsPricing(rs.getNetwork()).isPresent()
                            ? getSmsPricing(rs.getNetwork()).get().getCountryName()
                            : "Unknown");
                    rs.setNetworkName(getSmsPricing(rs.getNetwork()).isPresent()
                            ? getSmsPricing(rs.getNetwork()).get().getNetworkName()
                            : "Unknown");
                    rs.setPrefix(getSmsPricing(rs.getNetwork()).isPresent()
                            ? getSmsPricing(rs.getNetwork()).get().getPrefix()
                            : "Unknown");
                    rs.setClientName(smsUserService.queryUserInfoById(Integer.parseInt(rs.getUserId())).getUsername());
                    //rs.setSender(smsUser.getDefaultSender());
                })
                .collect(Collectors.toList());

        return reportVOList;
    }


    private Optional<SmsPricing> getSmsPricing(String network) {
        if (StringUtils.isEmpty(network)) {
            return Optional.empty();
        }
        final Map<String, SmsPricing> smsPricingMap = getStringSmsPricingMap();
        if (CollectionUtils.isEmpty(smsPricingMap)) {
            return Optional.empty();
        }
        final SmsPricing smsPricing = smsPricingMap.get(network);
        if (Objects.isNull(smsPricing)) {
            return Optional.empty();
        }
        return Optional.of(smsPricing);
    }

    private Map<String, SmsPricing> getStringSmsPricingMap() {
        return pricingService.queryPricingGroupByCountryCodeAndNetworkCode()
                .stream()
                .filter(smsPricing -> StringUtils.isNotEmpty(smsPricing.getNetworkCode()))
                .collect(Collectors.toMap(SmsPricing::getNetworkCode, Function.identity()));
    }
}
